package org.java.order.service.impl;

import com.rabbitmq.client.Channel;
import io.seata.spring.annotation.GlobalTransactional;
import org.java.common.entity.Cart;
import org.java.common.util.JsonUtils;
import org.java.order.conf.RabbitMqConfig;
import org.java.order.dao.OrderMapper;
import org.java.order.entity.Order;
import org.java.order.feigns.SkuClient;
import org.java.order.service.RabbitMqService;
import org.java.order.service.RedisService;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.annotation.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.Hashtable;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

/**
 * @author WHQ
 * @version 1.0
 * @date 2022-3-18 0018 下午 2:14
 */
//@RabbitListener(
//        bindings = @QueueBinding(
//                value = @Queue(value = "shopping_dlx_queue",autoDelete = "false"),
//                exchange = @Exchange(value = "shopping_dlx_exchange"),
//                key = "dlx.#"
//        )
//)
@Service
public class RabbitMqServiceImpl implements RabbitMqService {
    @Autowired
    private SkuClient skuClient;
    @Autowired
    private OrderMapper orderMapper;
    /**
     * 监听死信队列，指定时间内如果订单为支付，那么库存进行回滚
     * 如果已支付，不做操作
     * @param json
     */
    @RabbitListener(queues = RabbitMqConfig.DELAYED_QUEUE_NAME)
//    @RabbitHandler
    @Override
    @GlobalTransactional(name = "seata-server",rollbackFor = Exception.class)
    public void listeningToDlx(String json, Message message, Channel channel) {
        try {
            //设置不公平分发原则，如果该消费者算力强，就多消费消息，反之接收消息减少(能者多劳原则)
            channel.basicQos(1);
            System.out.println("进入死信队列");
            Map<String, String> map = JsonUtils.parseMap(json, String.class, String.class);
            String tradeNum = map.get("tradeNum");
            String carts = map.get("carts");
            List<Cart> list = JsonUtils.parseList(carts, Cart.class);
            //根据订单号查询订单是否支付
            Boolean flag=orderMapper.selectOrderStateByOrderId(tradeNum);
            if (flag==null){
                throw new RuntimeException("该订单不存在!");
            }
            if (!flag){
                System.out.println("订单未支付");
                System.out.println("订单时间已过，订单未支付，对订单进行库存回滚");
                for (Cart cart : list) {
                    //回滚库存
                    skuClient.rollbackInventory(cart.getSkuId(),cart.getNum().longValue());
                }
                //修改超时状态
                orderMapper.updateOrderTimeoutStateByOrderId(tradeNum);
            }
            System.out.println("处理成功!");
            //确认消息已经消费成功
//            channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
            try {
                //第一个参数是消息的标记(消息的主键)，第二个参数是是否批量应答multiple
                /**
                 * 假设channel中有5，6，7，8个消息，当前tag是8，此时如果将第二个参数填写为true
                 * 5-8这些还未确认应答的消息都会收到应答
                 * 如果为false，只有当前消息对收到应答
                 * 一般设置为false
                 */
                channel.basicAck(message.getMessageProperties().getDeliveryTag(),false);
            } catch (IOException e) {
                e.printStackTrace();
            }
        } catch (Exception runtimeException) {
            runtimeException.printStackTrace();
            //出现异常拒绝当前消息，并且把消息返回原队列
            try {
                channel.basicNack(message.getMessageProperties().getDeliveryTag(),false,true);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}
